﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Security.Permissions;
using Microsoft.Win32;
using System.Diagnostics;
using CalemShop.Classes;
using System.Collections;
using System.Drawing.Printing;
using System.IO;
using System.Drawing.Imaging;
using System.Threading;
using System.Media;
namespace CalemShop.Forms
{
    public partial class FrmSale : FrmBaseDock
    {
        #region class Bill Printing
        public class BillPrinting
        {
            public string seller;
            public long invoiceId;
            public string createdDate;
            public ArrayList cartItems;
            public decimal totalCartMoney;
            public bool isDiscount;
            public decimal discountPercent;

            public BillPrinting()
            {
            }

            public BillPrinting(string seller, long invoiceId, string createdDate, ArrayList cartItems, decimal totalCartMoney, bool isDiscount, decimal discountPercent)
            {
                this.seller = seller;
                this.invoiceId = invoiceId;
                this.createdDate = createdDate;
                this.cartItems = cartItems;
                this.totalCartMoney = totalCartMoney;
                this.discountPercent = discountPercent;
                this.isDiscount = isDiscount;
            }
        }

        #endregion
        private const int HUMAN_TYPING = 35;
        private Stopwatch typingMonitor;
        private StringBuilder barcodeBuffer = new StringBuilder();
        private DataTable itemSource;
        private decimal discountCurrentPercent = 0;
        private static ArrayList printingQueue = new ArrayList();
        private Thread printingThread;
        private bool isStartPrintingThread = false;
        private int FromSaleID = 0;
        private static SoundPlayer sound = null;
        private Customer currentCustomer = null;

        #region Fonts
        PrintDocument doc = new PrintDocument();
        static Font fontBody = new Font("Verdana", 11);
        static Font fontHeader = new Font("Verdana", 11, FontStyle.Bold);
        static Font fontFooter = new Font("Verdana", 9);
        static Font fontFooterBold = new Font("Verdana", 9, FontStyle.Bold);
        #endregion

        protected override void InitResource()
        {
            typingMonitor = new Stopwatch();
            typingMonitor.Start();
            printingThread = new Thread(new ThreadStart(PrintBillInQueue));
            printingThread.IsBackground = true;
            isStartPrintingThread = true;
            sound = new SoundPlayer(RuntimeData.GetSoundCompletePath());
            printingThread.Start();
        }


        private void FrmSale_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.F5:
                    e.Handled = true;
                    DoCashBill();
                    return;
            }

            if (txtMaSP.Focused)
            {
                e.Handled = false;
                barcodeBuffer.Clear();
                return;
            }

            if (e.KeyCode == Keys.Enter)
            {
                typingMonitor.Stop();
                long n = typingMonitor.ElapsedMilliseconds;
                typingMonitor.Reset();
                typingMonitor.Start();
                if (n < HUMAN_TYPING)
                {
                    //TODO Barcode reader;
                    OnBarCodeInputData(barcodeBuffer.ToString());
                }

                barcodeBuffer.Clear();
            }
            else
            {
                typingMonitor.Reset();
                typingMonitor.Start();
                if (char.IsLetterOrDigit((char)e.KeyCode))
                {
                    KeysConverter kc = new KeysConverter();
                    barcodeBuffer.Append(kc.ConvertToString(e.KeyCode));
                }
            }
        }

        public FrmSale(FrmCalemShop shop)
            : base(shop)
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            txtMaSP.AutoCompleteSource = AutoCompleteSource.CustomSource;
            txtMaSP.AutoCompleteMode = AutoCompleteMode.Suggest;
        }

        public int FormIndex
        {
            set { this.FromSaleID = value; }
            get { return this.FromSaleID; }
        }

        public void SetPrinterName(string printerName)
        {
            doc.PrinterSettings.PrinterName = printerName;
        }

        private void FrmSale_Load(object sender, EventArgs e)
        {
            this.Enabled = false;
            this.groupDiscount.Enabled = false;
            this.groupDiscount.DataBindings.Add("Enabled", chDiscount, "Checked");
            this.txtDiscountedMoney.DataBindings.Add("Enabled", radioDiscountByMoney, "Checked");
            this.txtDiscountPercent.DataBindings.Add("Enabled", radioDiscountByPercent, "Checked");


            this.dateMakeInvoice.Enabled = false;
            this.dateMakeInvoice.DataBindings.Add("Enabled", chChangeDate, "Checked");
            doc.PrintPage += new PrintPageEventHandler(Bill_PrintPage);
            backgroundWorker.RunWorkerAsync();
        }

        private void FocusBarcodeInput()
        {
            if (txtMaSP.Focused == false)
            {
                ActiveControl = txtMaSP;
            }
        }

        public override void FormActived()
        {
            FocusBarcodeInput();
            DBConnection.ConnectionString = RuntimeData.GetSqlConnectionString();
        }

        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            LoadShopData();
        }

        private void LoadShopData()
        {
            try
            {
                backgroundWorker.ReportProgress(50);
                itemSource = DataManager.Instance.LoadItems();
                listStaff.DataSource = DataManager.Instance.LoadStaffs();
                backgroundWorker.ReportProgress(100);
            }
            catch (Exception e)
            {
                Reporter.WriteErrorEx(e);
            }
        }

        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            CalemShop.UpdateProgressBar(e.ProgressPercentage, "Load stock items ...");
        }

        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            listStaff.DisplayMember = "account";
            listStaff.ValueMember = "account";
            txtMaSP.AutoCompleteCustomSource = DataManager.Instance.ItemKeyCollection;
            CalemShop.UpdateProgressBar(-1, null);
            this.Enabled = true;
            FocusBarcodeInput();
        }

        private void OnBarCodeInputData(string input)
        {
            try
            {
                if (txtMaSP.Focused == false)
                {
                    FocusBarcodeInput();
                }

                txtMaSP.Text = input;
                if (txtMaSP.Text.StartsWith("CB") || txtMaSP.Text.StartsWith("CW") || txtMaSP.Text.StartsWith("CG"))
                {
                    DoProcessCustomerService(txtMaSP.Text);
                    return;
                }
                OnAddItemToCart(input.ToUpper());
            }
            catch (Exception e)
            {
                Reporter.WriteErrorEx(e);
            }
        }

        private DataRow GetItemRowByAutoKey(ref string autoKey)
        {
            try
            {
                int key = 0;
                int.TryParse(autoKey, out key);
                if (key > 0)
                {
                    return itemSource.Rows.Find(autoKey);
                }
                else
                {
                    key = DataManager.Instance.GetItemAutokeyByItemId(autoKey);
                    if (key > 0)
                    {
                        autoKey = key.ToString();
                    }
                    return itemSource.Rows.Find(key);
                }
            }
            catch (Exception e)
            {
                return null;
            }
        }

        private void OnAddItemToCart(string itemKey)
        {
            DataRow r = GetItemRowByAutoKey(ref itemKey);
            if (r != null)
            {
                int stt = cartView.Items.Count + 1;
                decimal price = decimal.Parse(r["price"].ToString());
                ListViewItem item = GetItemFormCart(itemKey);
                if (item == null)
                {
                    item = new ListViewItem(new string[] {stt.ToString(), 
                    r["autoKey"].ToString(),  r["itemName"].ToString(),
                    "1", price.ToString("#,0"), price.ToString("#,0")});
                    item.SubItems[clPrice.Index].Tag = price;
                    item.SubItems[clMSP.Index].Tag = r["itemId"];
                    cartView.Items.Add(item);
                    item.Tag = itemKey;
                }
                else
                {
                    int amount = 1;
                    int.TryParse(item.SubItems[clAmount.Index].Text, out amount);
                    amount++;
                    item.SubItems[clAmount.Index].Text = amount.ToString();

                    decimal money = price * amount;
                    item.SubItems[clMoney.Index].Text = money.ToString("#,0");

                }

                //DoUpdateSumCart();
                cartView.Items[item.Index].ForeColor = Color.Blue;
                txtSLTon.Value = (int)r["amount"];
                ApplyDiscountIfAvaiable();
                PlayCompleteSound();
                txtMaSP.Text = string.Empty;
            }
            else
            {
                txtSLTon.Value = 0;
            }
        }

        private void txtMaSP_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Handled)
            {
                return;
            }

            if (e.KeyCode == Keys.Enter)
            {
                e.Handled = true;
                if (txtMaSP.Text.StartsWith("CB") || txtMaSP.Text.StartsWith("CW") || txtMaSP.Text.StartsWith("CG"))
                {
                    DoProcessCustomerService(txtMaSP.Text);
                    return;
                }
                OnAddItemToCart(txtMaSP.Text.ToUpper());
                e.SuppressKeyPress = false;
            }
        }

        private ListViewItem GetItemFormCart(string itemKey)
        {
            foreach (ListViewItem i in cartView.Items)
            {
                string key = i.SubItems[clMSP.Index].Text;
                if (string.Compare(itemKey, key, true) == 0)
                {
                    return i;
                }
            }

            return null;
        }

        private void listCart_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                e.Handled = true;
                DoDeleteCartItem();
            }
            else if (e.KeyCode == Keys.Left && e.Control)
            {
                e.Handled = true;
                DoEditCartItemMount(false);
            }
            else if (e.KeyCode == Keys.Right && e.Control)
            {
                e.Handled = true;
                DoEditCartItemMount(true);
            }
        }

        private void DoDeleteCartItem()
        {
            if (cartView.SelectedItems.Count > 0)
            {
                ListViewItem item = cartView.SelectedItems[0];
                cartView.Items.Remove(item);
                int index = 1;
                foreach (ListViewItem i in cartView.Items)
                {
                    i.SubItems[clSTT.Index].Text = (index).ToString();
                    index++;
                }

                //DoUpdateSumCart();
                ApplyDiscountIfAvaiable();
            }
        }

        private void DoUpdateSumCart()
        {
            int totalAmount = 0;
            decimal totalMoney = 0;
            int amount;
            decimal money = 0;
            // Reset bill information
            txtTotalMoney.Value = 0;
            txtTotalMoney.Tag = 0;
            txtTotalAmount.Value = 0;

            foreach (ListViewItem i in cartView.Items)
            {
                int.TryParse(i.SubItems[clAmount.Index].Text, out amount);
                money = (decimal)i.SubItems[clPrice.Index].Tag;
                totalMoney += (money * amount);
                totalAmount += amount;
                i.ForeColor = Color.Black;
            }

            txtTotalMoney.Value = totalMoney;
            txtTotalMoney.Tag = totalMoney;
            txtTotalAmount.Value = totalAmount;
        }

        private void DoEditCartItemMount(bool isIncrease)
        {
            if (cartView.SelectedItems.Count > 0)
            {
                ListViewItem item = cartView.SelectedItems[0];
                int amount = 0;
                int.TryParse(item.SubItems[clAmount.Index].Text, out amount);
                if (isIncrease)
                {
                    amount++;
                }
                else
                {
                    if (amount > 1)
                    {
                        amount--;
                    }
                }

                item.SubItems[clAmount.Index].Text = amount.ToString();
                int price = 0;
                int.TryParse(item.SubItems[clPrice.Index].Tag.ToString(), out price);
                decimal money = price * amount;
                item.SubItems[clMoney.Index].Text = money.ToString("#,0");
                //DoUpdateSumCart();
                ApplyDiscountIfAvaiable();
            }
        }

        private void listCart_ColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
        {
            e.Cancel = true;
            e.NewWidth = cartView.Columns[e.ColumnIndex].Width;
        }

        private void txtDiscountedMoney_ValueChanged(object sender, EventArgs e)
        {
            if (txtDiscountedMoney.Value > 0)
            {
                DoDiscountByMoney();
            }
            else if (txtDiscountedMoney.Value == 0)
            {
                DoUpdateSumCart();
            }
        }

        protected override void ReleaseResource()
        {
            if (printingThread != null)
            {
                this.isStartPrintingThread = false;
                printingThread.Interrupt();
            }
        }

        #region Discounting

        private decimal GetDiscountPercent()
        {
            if (!chDiscount.Checked)
            {
                return 0;
            }

            return discountCurrentPercent;
        }

        private void DoDiscountByMoney()
        {
            DoUpdateSumCart();
            if (chDiscount.Checked && radioDiscountByMoney.Checked)
            {
                decimal totalMoney = (decimal)txtTotalMoney.Tag;
                if (txtTotalMoney.Value != 0 && txtTotalMoney.Value >= txtDiscountedMoney.Value)
                {
                    discountCurrentPercent = (txtDiscountedMoney.Value * 100) / txtTotalMoney.Value;
                    //discountCurrentPercent = Math.Round(discountCurrentPercent);
                    lbDiscountPercentDesc.Text = string.Format("Tương đương {0}%", Math.Round(discountCurrentPercent));
                    txtTotalMoney.Value = txtTotalMoney.Value - txtDiscountedMoney.Value;
                    lbTotalDiscount.Text = string.Format("Tổng tiền {0} VNĐ, chiết khấu:{1}%", totalMoney.ToString("#,0"), Math.Round(discountCurrentPercent));
                }
                else
                {
                    txtDiscountedMoney.Value = 0;
                    discountCurrentPercent = 0;
                    lbDiscountPercentDesc.Text = string.Format("Tương đương {0}%", 0);
                    lbTotalDiscount.Text = string.Empty;
                }

            }
        }

        private void DoDiscountByPercent()
        {
            DoUpdateSumCart();
            if (chDiscount.Checked && radioDiscountByPercent.Checked)
            {
                decimal totalMoney = (decimal)txtTotalMoney.Tag;
                if (txtTotalMoney.Value != 0)
                {
                    discountCurrentPercent = txtDiscountPercent.Value;
                    decimal moneyDiscount = Math.Round((discountCurrentPercent * txtTotalMoney.Value) / 100);
                    lbDiscountMoneyDesc.Text = string.Format("Tương đương {0} VNĐ", moneyDiscount.ToString("#,0"));
                    if (txtTotalMoney.Value >= moneyDiscount)
                    {
                        txtTotalMoney.Value = txtTotalMoney.Value - moneyDiscount;
                        lbTotalDiscount.Text = string.Format("Tổng tiền {0} VNĐ, chiết khấu:{1}%", totalMoney.ToString("#,0"), discountCurrentPercent);
                    }
                }
                else if(currentCustomer == null)
                {
                    txtDiscountPercent.Value = 0;
                    discountCurrentPercent = 0;
                    lbDiscountMoneyDesc.Text = string.Format("Tương đương {0} VNĐ", 0);
                    lbTotalDiscount.Text = string.Empty;
                }
            }
        }


        private void ApplyDiscountIfAvaiable()
        {
            if (chDiscount.Checked)
            {
                if (radioDiscountByMoney.Checked)
                {
                    DoDiscountByMoney();
                }
                else
                {
                    DoDiscountByPercent();
                }
            }
            else
            {
                DoUpdateSumCart();
            }
        }

        private void ResetDiscount()
        {
            discountCurrentPercent = 0;
            lbTotalDiscount.Text = string.Empty;
            DoUpdateSumCart();
        }

        private void ResetBill()
        {
            currentCustomer = null;
            txtMaSP.Text = string.Empty;
            txtTotalMoney.Value = 0;
            txtTotalMoney.Tag = 0;
            txtTotalAmount.Value = 0;
            cartView.Items.Clear();
            lbTotalDiscount.Text = string.Empty;
            chChangeDate.Checked = false;
            chDiscount.Checked = false;
            discountCurrentPercent = 0;
            lbTotalDiscount.Text = string.Empty;
            txtDiscountPercent.Value = 0;
            txtDiscountedMoney.Value = 0;
            txtSLTon.Value = 0;
            txtCustomer.Text = string.Empty;
        }

        private void txtDiscountPercent_ValueChanged(object sender, EventArgs e)
        {
            if (txtDiscountPercent.Value > 0)
            {
                DoDiscountByPercent();
            }
            else if (txtDiscountPercent.Value == 0)
            {
                DoUpdateSumCart();
            }
        }

        private void radioDiscountByPercent_CheckedChanged(object sender, EventArgs e)
        {
            if (radioDiscountByPercent.Checked)
            {
                ResetDiscount();
            }
        }

        private void chDiscount_CheckedChanged(object sender, EventArgs e)
        {
            if (chDiscount.Checked == false)
            {
                ResetDiscount();

            }
            else
            {
                if (radioDiscountByMoney.Checked)
                {
                    DoDiscountByMoney();
                }
                else
                {
                    DoDiscountByPercent();
                }
            }
        }

        private void radioDiscountByMoney_CheckedChanged(object sender, EventArgs e)
        {
            if (radioDiscountByMoney.Checked)
            {
                ResetDiscount();
            }
        }
        #endregion

        #region Cash Bill
        private void DoCashBill()
        {
            try
            {
                if (cartView.Items.Count == 0)
                {
                    return;
                }

                string createDateInDatabase = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
                string invoicePrintedDate = DateTime.Now.ToString("dd-MM-yyyy hh:mm:ss");
                if (chChangeDate.Checked)
                {
                    createDateInDatabase = dateMakeInvoice.Value.ToString("yyyy-MM-dd hh:mm:ss");
                    invoicePrintedDate = dateMakeInvoice.Value.ToString("dd-MM-yyyy hh:mm:ss");
                }

                string customer = txtCustomer.Text;
                if (string.IsNullOrEmpty(customer))
                {
                    customer = "customer";
                }

                decimal discount = GetDiscountPercent();
                ArrayList rowList = new ArrayList();
                // Duyet lai cac item trong cart
                foreach (ListViewItem i in cartView.Items)
                {
                    int amount = 0;
                    decimal price = 0;
                    int.TryParse(i.SubItems[clAmount.Index].Text, out amount);
                    price = (decimal)i.SubItems[clPrice.Index].Tag;
                    decimal money = (price * amount);
                    InvoiceRowEntity invoiceRow = new InvoiceRowEntity();
                    int.TryParse(i.SubItems[clMSP.Index].Text, out invoiceRow.autoKey);
                    invoiceRow.itemId = i.SubItems[clMSP.Index].Tag.ToString();
                    invoiceRow.itemName = i.SubItems[clItemName.Index].Text;
                    invoiceRow.price = (int)price;
                    invoiceRow.amount = amount;
                    invoiceRow.total = (int)money;
                    invoiceRow.ck = discount;
                    rowList.Add(invoiceRow);
                }

                DBConnection.ConnectionString = RuntimeData.GetSqlConnectionString();
                long msoHD = Database.createInvoiceBuying(createDateInDatabase, listStaff.Text, customer, rowList, discount);
                if (msoHD > 0)
                {
                    BillPrinting bill = CreatePrintingBill(listStaff.Text, msoHD, invoicePrintedDate, rowList, (decimal)txtTotalMoney.Tag,
                                chDiscount.Checked, discount);
                    // print ...
                    if (!chPrintInvoice.Checked)
                    {
                        try
                        {
                            this.Enabled = false;
                            AddPrintingQueue(bill);
                            ShowPrintBillPreview(bill, true);
                            if (CalemShop.InvoiceExplorer != null)
                            {
                                CalemShop.InvoiceExplorer.AddNewInvoiceId(msoHD);
                            }
                        }
                        catch (Exception ex)
                        {
                            Reporter.WriteErrorEx(ex);
                        }
                        finally
                        {
                            this.Enabled = true;
                        }
                    }
                    else
                    {
                        ShowPrintBillPreview(bill, true);
                        if (CalemShop.InvoiceExplorer != null)
                        {
                            CalemShop.InvoiceExplorer.AddNewInvoiceId(msoHD);
                        }
                    }

                    if (currentCustomer != null)
                    {
                        decimal d = (Decimal)txtTotalMoney.Tag;
                        int point = (int)(d / 1000);
                        currentCustomer.point += point;
                        DataManager.UpdateCustomerPoint(currentCustomer.customerId, point);
                    }
                    ResetBill();
                }
            }
            catch (Exception ex)
            {
                Reporter.WriteErrorEx(ex);
            }
        }

        private void DoRefundBill()
        {
            try
            {
                if (cartView.Items.Count == 0)
                {
                    return;
                }

                FrmConfirmReturnItem confirm = new FrmConfirmReturnItem();
                confirm.ShowInTaskbar = false;
                confirm.StartPosition = FormStartPosition.CenterScreen;
                if (confirm.ShowDialog(this) == DialogResult.Cancel)
                {
                    return;
                }

                string reason = confirm.txtReason.Text;
                string customer = txtCustomer.Text;
                if (string.IsNullOrEmpty(customer))
                {
                    customer = "customer";
                }

                decimal discount = GetDiscountPercent();
                ArrayList rowList = new ArrayList();
                // Duyet lai cai item trong cart
                foreach (ListViewItem i in cartView.Items)
                {
                    int amount = 0;
                    decimal price = 0;
                    int.TryParse(i.SubItems[clAmount.Index].Text, out amount);
                    price = (decimal)i.SubItems[clPrice.Index].Tag;
                    decimal money = (price * amount);
                    InvoiceRowEntity invoiceRow = new InvoiceRowEntity();
                    int.TryParse(i.SubItems[clMSP.Index].Text, out invoiceRow.autoKey);
                    invoiceRow.itemId = i.SubItems[clMSP.Index].Tag.ToString();
                    invoiceRow.itemName = i.SubItems[clItemName.Index].Text;
                    invoiceRow.price = (int)price;
                    invoiceRow.amount = amount;
                    invoiceRow.total = (int)money;
                    invoiceRow.ck = discount;
                    rowList.Add(invoiceRow);
                }

                DBConnection.ConnectionString = RuntimeData.GetSqlConnectionString();
                long msoHD = Database.createInvoiceReturning(listStaff.Text, customer, reason, rowList);
                if (msoHD > 0)
                {
                    if (CalemShop.InvoiceExplorer != null)
                    {
                        CalemShop.InvoiceExplorer.AddNewInvoiceId(msoHD);
                    }

                    PlayCompleteSound();
                    MessageBox.Show(this, "Trả hàng thành công, Hóa đơn trả hàng số : " + msoHD, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

                ResetBill();
            }
            catch (Exception e)
            {
                Reporter.WriteErrorEx(e);
            }
        }
        #endregion


        #region Printing

        public static BillPrinting CreatePrintingBill(string seller, long invoiceId, string createdDate, ArrayList cartItems, decimal totalCartMoney, bool isDiscount, decimal discountPercent)
        {
            return new BillPrinting(seller, invoiceId, createdDate, cartItems, totalCartMoney, isDiscount, discountPercent);
        }

        private void Bill_PrintPage(object sender, PrintPageEventArgs e)
        {
            try
            {
                if (printingQueue.Count > 0)
                {
                    Graphics g = e.Graphics;
                    BillPrinting bill = (BillPrinting)printingQueue[0];
                    printingQueue.RemoveAt(0);
                    PaintViewInvoice(g, bill.seller, bill.invoiceId, bill.createdDate, bill.cartItems, bill.totalCartMoney, bill.isDiscount, bill.discountPercent);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                this.Enabled = true;
            }
        }

        public static void AddPrintingQueue(BillPrinting bill)
        {
            try
            {
                lock (printingQueue)
                {
                    printingQueue.Add(bill);
                    Monitor.PulseAll(printingQueue);
                }
            }
            catch (Exception e)
            {
                Reporter.WriteErrorEx(e);
            }
        }


        private void PrintBillInQueue()
        {
            try
            {
                while (isStartPrintingThread)
                {
                    try
                    {
                        lock (printingQueue)
                        {
                            if (printingQueue.Count == 0)
                            {
                                Monitor.Wait(printingQueue);
                            }
                            else
                            {
                                doc.Print();
                            }
                            Thread.Sleep(100);
                        }
                    }
                    catch (ThreadInterruptedException ie)
                    {
                        isStartPrintingThread = false;
                        break;
                    }
                }
            }
            catch (Exception ee)
            {
                MessageBox.Show(ee.StackTrace);
                isStartPrintingThread = false;
            }
        }

        public static void PaintViewInvoice(Graphics g, string seller, long invoiceId, string createdDate, ArrayList cartItems, decimal totalCartMoney, bool isDiscount, decimal discountPercent)
        {
            // Paint header :
            float lineSep = 5;
            int lineW = 270;
            float fontH = fontHeader.GetHeight(g);
            float fontB = fontBody.GetHeight(g);
            float fontF = fontFooter.GetHeight(g);
            RectangleF rectF1 = new RectangleF(5, 5, lineW, fontH);
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            g.DrawString(RuntimeData.GetBillTitle(), fontHeader, Brushes.Black, rectF1, format);
            float y = lineSep + fontH + 15;

            rectF1 = new RectangleF(5, y, lineW, fontH);
            g.DrawString(RuntimeData.GetBillHeader(), fontHeader, Brushes.Black, rectF1, format);

            y += fontH + lineSep;
            rectF1 = new RectangleF(5, y, lineW, 3 * fontF);
            g.DrawString(RuntimeData.GetBillHomeAddress(), fontFooter, Brushes.Black, rectF1, format);
            y += fontH + 3 * lineSep;
            rectF1 = new RectangleF(5, y, lineW, fontF);
            g.DrawString("***************************", fontFooter, Brushes.Black, rectF1, format);
            rectF1 = new RectangleF(5, y + fontH, lineW, fontF);
            format.Alignment = StringAlignment.Near;
            g.DrawString("MSHĐ :" + invoiceId, fontFooterBold, Brushes.Black, rectF1, format);
            format.Alignment = StringAlignment.Far;
            g.DrawString(createdDate, fontFooter, Brushes.Black, rectF1, format);
            y += fontH + 3 * lineSep;
            // Draw Invoice row
            //------------------------------------------------------------------------------
            float x = 4;
            lineW = 275;
            y += fontH + 2 * lineSep;
            string tab4 = "    ";
            string tab8 = "        ";
            RectangleF rectBody = new RectangleF(x, y, lineW + 8, fontB);
            format.Alignment = StringAlignment.Near;
            g.DrawString("Mã S.Phẩm" + tab4 + "  SL" + tab8 + "Giá" + tab8 + "      T.Tiền", fontFooter, Brushes.Black, rectBody, format);
            //g.DrawRectangle(Pens.Black, Rectangle.Round(rectBody));
            g.DrawLine(Pens.Black, x, y + fontB, lineW, y + fontB);
            y += fontH + lineSep;

            RectangleF rectC1 = new RectangleF(x, y, 75, fontB);
            RectangleF rectC2 = new RectangleF(x + rectC1.Width + 2, y, 30, fontB);
            RectangleF rectC3 = new RectangleF(rectC2.X + rectC2.Width + 2, y, 75, fontB);
            RectangleF rectC4 = new RectangleF(rectC3.X + rectC3.Width + 2, y, 90, fontB);
            int index = 0;
            int sumAmount = 0;
            foreach (InvoiceRowEntity item in cartItems)
            {
                index++;
                sumAmount += item.amount;
                format.Alignment = StringAlignment.Far;
                g.DrawString(item.amount.ToString(), fontFooter, Brushes.Black, rectC2, format);
                format.Alignment = StringAlignment.Near;
                //g.DrawString(invoiceRow.itemId, fontFooter, Brushes.Black, rectC1, format);
                g.DrawString(item.autoKey.ToString(), fontFooter, Brushes.Black, rectC1, format);
                format.Alignment = StringAlignment.Far;
                g.DrawString(item.price.ToString("#,0"), fontFooter, Brushes.Black, rectC3, format);
                g.DrawString(item.total.ToString("#,0"), fontFooter, Brushes.Black, rectC4, format);

                //g.DrawRectangle(Pens.Black, Rectangle.Round(rectC1));
                //g.DrawRectangle(Pens.Black, Rectangle.Round(rectC2));
                //g.DrawRectangle(Pens.Black, Rectangle.Round(rectC3));
                //g.DrawRectangle(Pens.Black, Rectangle.Round(rectC4));

                rectC1.Y += fontB + lineSep;
                rectC2.Y = rectC1.Y;
                rectC3.Y = rectC1.Y;
                rectC4.Y = rectC1.Y;
            }

            g.DrawLine(Pens.Black, rectC1.X, rectC1.Y, lineW, rectC1.Y);
            // Ve sum cot so luong.
            rectC2.Y += 5;
            format.Alignment = StringAlignment.Far;
            g.DrawString(sumAmount.ToString(), fontFooter, Brushes.Black, rectC2, format);
            // ----------------------------------------------------------------
            rectC3.Y += 5;
            //format.Alignment = StringAlignment.Far;
            if (isDiscount && discountPercent > 0)
            {
                g.DrawString("Tổng:", fontFooter, Brushes.Black, rectC3, format);
            }
            else
            {
                g.DrawString("Tổng:", fontFooterBold, Brushes.Black, rectC3, format);
            }
            rectC4.Y = rectC3.Y;
            format.Alignment = StringAlignment.Far;
            //g.DrawString(txtTotal.Text, fontFooterBold, Brushes.Black, rectC4, format);
            g.DrawString(totalCartMoney.ToString("#,0"), fontFooterBold, Brushes.Black, rectC4, format);

            if (isDiscount && discountPercent > 0)
            {
                rectC3.Y += 5 + fontB;
                format.Alignment = StringAlignment.Near;
                RectangleF recDiscount = new RectangleF(rectC3.X, rectC3.Y, rectC3.Width + 20, rectC3.Height);
                g.DrawString(string.Format(@"Giảm {0}%", Math.Round(discountPercent).ToString("#.##")), fontFooter, Brushes.Black, recDiscount, format);
                rectC4.Y = rectC3.Y;
                format.Alignment = StringAlignment.Far;
                decimal discountMoney = Math.Round(totalCartMoney * discountPercent / 100);
                g.DrawString(discountMoney.ToString("-#,0"), fontFooterBold, Brushes.Black, rectC4, format);

                rectC3.Y += 5 + fontB;
                format.Alignment = StringAlignment.Near;
                g.DrawString("T.Tiền:", fontFooterBold, Brushes.Black, rectC3, format);
                rectC4.Y = rectC3.Y;
                format.Alignment = StringAlignment.Far;

                decimal paidMoney = totalCartMoney - discountMoney;
                g.DrawString(paidMoney.ToString("#,0"), fontFooterBold, Brushes.Black, rectC4, format);
            }

            rectC4.Y += 100;
            RectangleF rectFooter = new RectangleF(5, rectC4.Y, lineW, fontH);
            format.Alignment = StringAlignment.Center;
            g.DrawString("***** ***** ", fontFooter, Brushes.Black, rectFooter, format);
            rectFooter.Y += fontF + lineSep;
            g.DrawString(string.Format("Hotline: {0} ", RuntimeData.GetBillHotline()), fontFooter, Brushes.Black, rectFooter, format);
            rectFooter.Y += fontF + lineSep;
            g.DrawString(RuntimeData.GetBillURL(), fontFooter, Brushes.Black, rectFooter, format);
            rectFooter.Y += fontF + lineSep;
            g.DrawString("Nhân viên:" + seller, fontFooter, Brushes.Black, rectFooter, format);
            rectFooter.Y += fontF + 2 * lineSep;
            g.DrawString("----", fontFooter, Brushes.Black, rectFooter, format);
        }


        public static void PaintViewInvoice(Graphics g, BillPrinting bill)
        {
            if (bill != null)
            {
                PaintViewInvoice(g, bill.seller, bill.invoiceId, bill.createdDate, bill.cartItems, bill.totalCartMoney, bill.isDiscount, bill.discountPercent);
            }
        }

        private void ShowPrintBillPreview(BillPrinting bill, bool saveImage)
        {
            try
            {
                // Paint show review
                FrmPrintBillPreview frmPrintView = new FrmPrintBillPreview();
                frmPrintView.FormClosed += new FormClosedEventHandler(PrintViewFormClosed);
                frmPrintView.StartPosition = FormStartPosition.CenterScreen;
                frmPrintView.Bill = bill;
                frmPrintView.PrintBillDoc = doc;
                frmPrintView.Show(this);
                // store to HDD.
                if (saveImage)
                {
                    Bitmap bm = new Bitmap(291, 580);
                    Graphics g2 = Graphics.FromImage(bm);
                    g2.FillRectangle(Brushes.White, 0, 0, 291, 580);
                    PaintViewInvoice(g2, bill);
                    g2.Dispose();
                    string savePath = Path.Combine(BackupUtil.doCheckFolderInvoice(), bill.invoiceId + ".png");
                    bm.Save(savePath, ImageFormat.Png);
                    bm.Dispose();
                }
            }
            catch (Exception ex)
            {
                Reporter.WriteErrorEx(ex);
            }
        }

        private void PrintViewFormClosed(object sender, FormClosedEventArgs e)
        {
            this.txtMaSP.Focus();
        }

        #endregion

        #region Customer Service 
        private void DoProcessCustomerService(string cardSerial)
        {
            try
            {
                currentCustomer = DataManager.GetCustomerBySerial(cardSerial);
                if (currentCustomer != null)
                {
                    if (btClear.Visible == false)
                    {
                        btClear.Visible = true;
                    }
                    txtCustomer.Text = currentCustomer.customerName.ToUpper();
                    txtCustomer.Refresh();
                    if (cardSerial.StartsWith("CB."))
                    {
                        chDiscount.Checked = true;
                        radioDiscountByPercent.Checked = true;
                        txtDiscountPercent.Value = 15;
                    } if (cardSerial.StartsWith("CG."))
                    {
                        chDiscount.Checked = true;
                        radioDiscountByPercent.Checked = true;
                        txtDiscountPercent.Value = 10;
                    } if (cardSerial.StartsWith("CW."))
                    {
                        chDiscount.Checked = true;
                        radioDiscountByPercent.Checked = true;
                        txtDiscountPercent.Value = 5;
                    }

                    ApplyDiscountIfAvaiable();
                }
            }
            catch (Exception e)
            {
            }
        }
        #endregion

        private void btCash_Click(object sender, EventArgs e)
        {
            DoCashBill();
        }

        private void btRefund_Click(object sender, EventArgs e)
        {
            DoRefundBill();
        }

        #region sound
        public static void PlayCompleteSound()
        {
            try
            {
                if (sound == null)
                {
                    sound = new SoundPlayer(RuntimeData.GetSoundCompletePath());
                }
                sound.Play();
            }
            catch (Exception e)
            {
            }
        }
        #endregion

        private void btClear_Click(object sender, EventArgs e)
        {
            txtCustomer.Text = "___";
            chDiscount.Checked = false;
            currentCustomer = null;
            ResetDiscount();
            btClear.Visible = false;
        }
    }
}
